package start.spring.basic.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.baidu.fsg.uid.worker.WorkerIdAssigner;

import start.spring.basic.constant.CommonConstant;

/**
 * @Auther: wangzhongxing
 * @Date: 2020/1/13 17:52
 * @Description: https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md
 * <p>
 * 接入指引文档：https://blog.csdn.net/weixin_39338423/article/details/103972134
 * <p>
 * 百度id生成器
 * 两种生成器: DefaultUidGenerator、CachedUidGenerator。如对UID生成性能有要求, 请使用CachedUidGenerator
 * 对应Spring配置分别为: default-uid-spring.xml、cached-uid-spring.xml
 */
@Configuration
public class CachedUidGeneratorConfig {

    /**
     * disposableWorkerIdAssigner的入参对象类型最好使用 WorkerIdAssigner，
     * 否则其他地方引入CGLib动态代理的时候可能会导致代理混用的问题
     *
     * @param disposableWorkerIdAssigner
     * @return
     */
    @Bean
    public CachedUidGenerator cachedUidGenerator(WorkerIdAssigner disposableWorkerIdAssigner) {
        CachedUidGenerator cachedUidGenerator = new CachedUidGenerator();
        cachedUidGenerator.setWorkerIdAssigner(disposableWorkerIdAssigner);
        /**
         * 关于UID比特分配的建议：
         * 对于并发数要求不高、期望长期使用的应用, 可增加timeBits位数, 减少seqBits位数.
         * 例如节点采取用完即弃的WorkerIdAssigner策略, 重启频率为12次/天, 那么配置成：
         * {"workerBits":23,"timeBits":31,"seqBits":9}时, 可支持28个节点以整体并发量14400 UID/s的速度持续运行68年.
         *
         * 对于节点重启频率频繁、期望长期使用的应用, 可增加workerBits和timeBits位数, 减少seqBits位数.
         * 例如节点采取用完即弃的WorkerIdAssigner策略, 重启频率为24*12次/天, 那么配置成：
         * {"workerBits":27,"timeBits":30,"seqBits":6}时, 可支持37个节点以整体并发量2400 UID/s的速度持续运行34年.
         */
        // 以下为可选配置, 如未指定将采用默认值
        cachedUidGenerator.setEpochStr(CommonConstant.EPOCH_STR);
        // timeBits，相对于时间基点的增量值，单位：秒，可使用的时间为2^timeBis 秒
        // 例如：timeBits=29，则可使用2^29秒，约17年，timeBits=30，则可使用2^30秒，约34年，timeBits=31，则可使用2^31秒，约68年
        cachedUidGenerator.setTimeBits(29);
        // 机器id，最多可支持2^23约 8388608 次机器启动(1000个节点，每个节点每天重启一次，可使用年数为： 8388608/(1000*365) = 22.98年)。内置实现为在启动时由数据库分配，默认分配策略为用后即弃，
        // 每次启动都会重新生成一批ID，因此重启次数也是会有限制的。
        cachedUidGenerator.setWorkerBits(23);
        // 每秒下的并发序列，11 bits可支持每个节点每秒2^11 = 2048个并发。
        cachedUidGenerator.setSeqBits(11);

        //RingBuffer size扩容参数, 可提高UID生成的吞吐量
        //默认:3， 原bufferSize=8192, 扩容后bufferSize= 8192 << 3 = 65536
        cachedUidGenerator.setBoostPower(3);
        // 指定何时向RingBuffer中填充UID, 取值为百分比(0, 100), 默认为50
        // 举例: bufferSize=1024, paddingFactor=50 -> threshold=1024 * 50 / 100 = 512.
        // 当环上可用UID数量 < 512时, 将自动对RingBuffer进行填充补全
        //<property name="paddingFactor" value="50"></property>

        //另外一种RingBuffer填充时机, 在Schedule线程中, 周期性检查填充
        //默认:不配置此项, 即不实用Schedule线程. 如需使用, 请指定Schedule线程时间间隔, 单位:秒
        cachedUidGenerator.setScheduleInterval(60L);

        return cachedUidGenerator;
    }
}
